// WorkSchedulerDlg.cpp : implementation file
//

#include "stdafx.h"
#include "WorkScheduler.h"
#include "WorkSchedulerDlg.h"
#include "SimpleTray.h"
#include "WorkSchedulerOptionsDlg.h"
#include "WorkReportDlg.h"
#include "AboutDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

//work timer id
#define TIMER_WORK 1

//cycle time: 2 seconds
#define WORK_TIMER_CYCLE 900

// Tray notification message
#define WM_TRAYNOTIFY						(WM_APP + 111)


// CWorkSchedulerDlg dialog




CWorkSchedulerDlg::CWorkSchedulerDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CWorkSchedulerDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	m_uiTimerWork = TIMER_WORK;
	m_bMinimized = false;
	m_pTray = new CSimpleTray(WM_TRAYNOTIFY);
	m_bFiredPopup = false;
}

CWorkSchedulerDlg::~CWorkSchedulerDlg()
{
	delete m_pTray;
}

void CWorkSchedulerDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CWorkSchedulerDlg, CDialog)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_BTN_START_WORK, &CWorkSchedulerDlg::OnBnClickedBtnStartWork)
	ON_MESSAGE(WM_TRAYNOTIFY, OnTrayNotify)
	ON_COMMAND(ID_SHOW_MAIN_DLG, OnShowWS)	
	ON_COMMAND(ID_EXIT_APP, OnExit)
	ON_COMMAND(ID_STOP_WORK, OnStopWork)
	ON_COMMAND(ID_FILE_CLOSE, OnExit)
	ON_COMMAND(ID_OPTIONS_PREFERENCES, OnOpenPreferences)
	ON_COMMAND(ID_FILE_REPORT, OnOpenReport)
	ON_COMMAND(ID_HELP_ABOUT, OnOpenAboutDlg)
	ON_WM_TIMER()
	ON_BN_CLICKED(IDC_TO_SYSTRAY, &CWorkSchedulerDlg::OnBnClickedToSystray)
END_MESSAGE_MAP()


// CWorkSchedulerDlg message handlers

BOOL CWorkSchedulerDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	// TODO: Add extra initialization here
	UpdateControlsState();

	return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CWorkSchedulerDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CWorkSchedulerDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


void CWorkSchedulerDlg::OnBnClickedBtnStartWork()
{
	if (m_WorkSchedulingLogic.GetState() == WorkSchedulingLogic::STATE_STOPPED)
	{
		CString csWorkTime;
		if (0 == GetDlgItemText(IDC_EDIT_WORK_TIME, csWorkTime))
			return;

		int workTime = _wtoi(csWorkTime);
		if (workTime <= 0)
			return;

		m_bFiredPopup = false;
		CTimeSpan workTimeSpan(0,0,workTime,0);
		//CTimeSpan workTimeSpan(0,0,0,3);
		m_WorkSchedulingLogic.SetMaxWorkTime(workTimeSpan);
		m_WorkSchedulingLogic.StartWork();
		m_uiTimerWork = SetTimer(TIMER_WORK, WORK_TIMER_CYCLE, NULL);
		UpdateControlsState();
	}
	else
	{
		OnStopWork();
	}
}

void CWorkSchedulerDlg::OnTimer(UINT nIDEvent)
{
	if (nIDEvent==m_uiTimerWork)
	{
		m_WorkSchedulingLogic.Tick();
		UpdateControlsState();
	}
}

void CWorkSchedulerDlg::MinimizeToTray(bool bMinimize)
{
	if (m_bMinimized == bMinimize)
	{
		if (!m_bMinimized)
			SetForegroundWindow();
		return;
	}
	
	m_pTray->SetIcon( m_hIcon ); // application icon

	m_pTray->SetTooltip(GetSystrayString());

	if (bMinimize)
	{
		m_bMinimized = m_pTray->Show();
		ShowWindow((m_bMinimized ? SW_HIDE : SW_SHOW));
	}
	else
	{
		m_pTray->Hide();
		ShowWindow(SW_SHOW);
		SetActiveWindow();
		m_bMinimized = false;
	}

}

long CWorkSchedulerDlg::OnTrayNotify(WPARAM wParam, LPARAM lParam)
{
	switch ( lParam )
	{
	case WM_LBUTTONDBLCLK:
		{	// left click, activate window
			// we would do here the same thing as if
			// the user clicked the "show dialog" menu
			// so don't duplicate the code
			SetForegroundWindow();
			OnShowWS();
		}
		break;
	case WM_RBUTTONUP:
		{	// right click, show popup menu
			

			CMenu mpopup;
			mpopup.CreatePopupMenu();			
			mpopup.AppendMenu(MF_STRING,ID_SHOW_MAIN_DLG,_T("Show WorkScheduler"));
			if (m_WorkSchedulingLogic.GetState() == WorkSchedulingLogic::STATE_WORKING)
				mpopup.AppendMenu(MF_STRING, ID_STOP_WORK, _T("Stop Work"));
			mpopup.AppendMenu(MF_STRING,ID_EXIT_APP,_T("Exit"));

			CPoint loc;
			GetCursorPos( &loc );
			SetForegroundWindow();
			TrackPopupMenu(mpopup.m_hMenu, 0, loc.x, loc.y, 0, m_hWnd, NULL);
		}
		break;
	default:
		// do nothing
		break;
	}
	return 1;
}

void CWorkSchedulerDlg::OnShowWS() 
{
	MinimizeToTray(false);
}

void CWorkSchedulerDlg::OnExit()
{
	EndDialog(0);
}
void CWorkSchedulerDlg::OnBnClickedToSystray()
{
	MinimizeToTray(true);
}

CString CWorkSchedulerDlg::GetRemainingTimeString(const CTimeSpan& remainingTimeSpan)
{
	CString csTime;
	bool bNegative = false;
	int hours = (int)remainingTimeSpan.GetTotalHours();
	if (hours < 0)
	{
		bNegative = true;
		hours = -hours;
	}

	if (hours > 0)
	{
		CString csHours;
		csHours.Format(_T("%d hours "), hours);
		csTime += csHours;
	}

	int minutes = (int)remainingTimeSpan.GetMinutes();
	if (minutes < 0)
	{
		bNegative = true;
		minutes = -minutes;
	}

	if (minutes > 0)
	{
		CString csMinutes;
		csMinutes.Format(_T("%d minutes "), minutes);
		csTime += csMinutes;
	}

	int seconds = (int)remainingTimeSpan.GetSeconds();
	if (seconds < 0)
	{
		bNegative = true;
		seconds = -seconds;
	}
	CString csSeconds;
	csSeconds.Format(_T("%d seconds"), seconds);
	csTime += csSeconds;

	CString csPrefix = (bNegative ? _T("Time exceeded by: ") : _T("Time remaining: "));
	return csPrefix + csTime;
}

CString CWorkSchedulerDlg::GetSystrayString()
{
	CString csToolTip = _T("WorkScheduler");
	return csToolTip;
}

void CWorkSchedulerDlg::OnStopWork()
{
	KillTimer(m_uiTimerWork);
	m_WorkSchedulingLogic.StopWork();
	UpdateControlsState();
}

void CWorkSchedulerDlg::UpdateControlsState()
{
	WorkSchedulingLogic::eWorkState logicState = m_WorkSchedulingLogic.GetState();
	switch (logicState)
	{
	case WorkSchedulingLogic::STATE_STOPPED:
		{
			SetDlgItemText(IDC_BTN_START_WORK,_T("Start"));
			GetDlgItem(IDC_LABEL_MESSAGE)->ShowWindow(SW_HIDE);
			GetDlgItem(IDC_LABEL_REMAINING)->ShowWindow(SW_HIDE);
			if (m_bMinimized)
				m_pTray->SetTooltip(GetSystrayString());
			break;
		}

	case WorkSchedulingLogic::STATE_WORKING:
		{
			SetDlgItemText(IDC_BTN_START_WORK,_T("Stop"));
			bool bShouldTakeBreak = m_WorkSchedulingLogic.ShouldTakeBreak();
			if (bShouldTakeBreak)
			{
				SetDlgItemText(IDC_LABEL_MESSAGE, _T("Take A Break!!"));
				GetDlgItem(IDC_LABEL_MESSAGE)->ShowWindow(SW_SHOW);
				if (!m_bFiredPopup)
				{
					MinimizeToTray(false);
					m_bFiredPopup = true;
				}
			}
			else
			{
				GetDlgItem(IDC_LABEL_MESSAGE)->ShowWindow(SW_HIDE);
			}
			
			CTimeSpan timeTillBreak = m_WorkSchedulingLogic.TimeTillBreak();
			CString csRemainingTimeString = GetRemainingTimeString(timeTillBreak);
			if (m_bMinimized)
			{
				m_pTray->SetTooltip(csRemainingTimeString);
			}
			else
			{
				SetDlgItemText(IDC_LABEL_REMAINING, csRemainingTimeString);
				GetDlgItem(IDC_LABEL_REMAINING)->ShowWindow(SW_SHOW);
			}
			break;
		}
	case WorkSchedulingLogic::STATE_ON_BREAK:
		{
			SetDlgItemText(IDC_BTN_START_WORK,_T("Stop"));
			GetDlgItem(IDC_LABEL_REMAINING)->ShowWindow(SW_HIDE);
			SetDlgItemText(IDC_LABEL_MESSAGE, _T("On break"));
			GetDlgItem(IDC_LABEL_MESSAGE)->ShowWindow(SW_SHOW);
			m_bFiredPopup = false;
			if (m_bMinimized)
				m_pTray->SetTooltip(GetSystrayString());
			break;
		}
	}
}

void CWorkSchedulerDlg::OnOpenPreferences()
{
	CWorkSchedulerOptionsDlg optionsDlg(NULL, m_WorkSchedulingLogic);
	optionsDlg.DoModal();
}

void CWorkSchedulerDlg::OnOpenReport()
{
	CWorkReportDlg reportDlg(NULL, m_WorkSchedulingLogic.GetWorkCycles());
	reportDlg.DoModal();
}

void CWorkSchedulerDlg::OnOpenAboutDlg()
{
	CAboutDlg aboutDlg;
	aboutDlg.DoModal();
}
